% 
% CIS 554 Programming Paradigms
% Fall 2016
% Kieraj Mumick
%
% Homework 2
% The Knights Who Say "Ni"
% Make your way through the woods past the nights who guard your way!

/**
 *  Map:
 *
 *                 [GOAL]
 *                   |
 *          [Knights Who Say Ni]
 *    (Needs Shrubbery to get through)
 *                   |                           [Crone]
 *                   |            (Needs "Ni" to be said to get shrubbery)
 *                   |                {Hidden inside the small villiage}
 *                [START]---------------------[Small Village]
 *                   |                              |
 *             [Large Village]       [The Mightiest Tree in the Forest] 
 *                                               [Herring]
 *                                      (Needed to cut down the tree)
 *                                          {Hidden on the tree}
 * 
 *
 *
 */  


 /**
  *  Storyline:
  *  
  *  You are on your way to find the Holy Grail. North is the continuation
  *  of your path. South is the path you have already travelled on. East
  *  is a small village.
  *
  *  You go North. Now, to your north are the Knights who say Ni. To the south
  *  Is the start location.
  *  
  *  You go North. Now, to your north are the Knights who say Ni. To the south
  *  is the pathway you were walking on to get here.
  *     You ask the Knights "May I get through?". The knights demand a
  *  sacrifice! You tell the knights, "Please, I simply would like to pass through."
  *  In response, the knights shout "NI!", and exclaim that they will continue to
  *  shout "Ni!" until you appease them with a shrubbery. You cannot stand the word
  *  "Ni", so you must now find a shrubbery. 
  *
  *  You now travel back south to the walking path.
  *  
  *  You now travel back south to the original destination.
  * 
  *  You now travel east to the small village. 
  *
  *  You look around, you see an old crone. You talk to the crone. You ask the crone
  *  where you can find a shrubbery. She asks you a bunch of questions, and you
  *  end up admitting that you need the shrubbery to get through the Knights who say
  *  "Ni". Because of this, she refuses to help you. 
  *
  *  You look into your vocabulary, and realize you can say the word "Ni!", which
  *  will likely torture the old crone. 
  *
  *  You say "Ni". She flinches. You say "Ni" again, she flinches again. A man on a
  *  horse rides by you and says that he laments the lack of law and order that
  *  allows them to say "Ni" to an old woman. You now have to explain to this man
  *  why you are doing this.
  *
  *  You tell him the story of the knights who say Ni.
  *
  *  He gives you a shrubbery!
  *
  *  You now go back to the knights who say Ni! You present them with a shrubbery.
  *  However, they now inform you that you can't pass through, as they are
  *  no longer the Knights who say Ni, but rather the Knights who say
  *  "Ekke Ekke Ekke Ekke Ptang Zoo Boing!". They inform you that in order to pass
  *  by, you will need to bring them... another shrubbery, which needs to
  *  be placed next to, but slightly higher than the first one! Additionally, 
  *  it is said that you must also cut down the mightiest tree in the forest, 
  *  with a Herring! How do you respond?
  *  
  *  You say "It can't be done"! The knights recoil as though they were hit by an
  *  arrow. It immediately becomes obvious that the knights are unable to 
  *  tolerate the word "It". The knights have now retreated, and the pathway is
  *  now open! You can pass through!
  *  
  */

:- dynamic i_am_at/1, at/2, holding/1, vocabulary/1, exists/1, talking_to/1, time_counter/1.
:- retractall(at(_, _)), retractall(i_am_at(_)).

time_counter(0).

place(fork_in_road).
place(large_village).
place(small_village).
place(knights_who_say_ni).
place(the_mightiest_tree_in_the_forest).
place(goal).

vocabulary(it).

describe(fork_in_road) :-
  write('You are on your way to find the Holy Grail. North is the continuation'), nl,
  write('of the trail. West is a large village. East is a small village.'), nl,
  write('Which way are you going to go?'), nl.

describe(large_village) :-
  write('You are in a large village! There are many citizens, witches, and'), nl,
  write('services around. However, right now, the villagers are on holiday,'), nl,
  write(' and the entire village is deserted. There is no one here, and'), nl,
  write('there is nothing to explore.'), nl.

describe(small_village) :-
  write('You have arrived at the small village. To your west is the fork in the road,'), nl,
  write('and to your south is the mightiest tree in all the land. The small village is home to'), nl,
  write('an old crone, who sees almost everyone that passes by the village.'), nl,
  write('There is also an important path which goes through this village which'), nl,
  write('is used by many travellers on their way to the large village.'), nl, nl,
  write('To talk to the old crone, type "talk_to(old_crone)."').

describe(knights_who_say_ni) :-
  exists(shrubbery),
  holding(shrubbery),
  assert(talking_to(knights_who_say_ni)),
  write('You present the Knights who say "Ni" with a shrubbery.'), nl,
  write('However, they now inform you that you can''t pass through, as they are'), nl,
  write('no longer the Knights who say Ni, but rather the Knights who say'), nl,
  write('"Ekke Ekke Ekke Ekke Ptang Zoo Boing!". They inform you that in order to pass'), nl,
  write('by, you will need to bring them... another shrubbery, which needs to'), nl,
  write('be placed next to, but slightly higher than the first one! Additionally, '), nl,
  write('it is said that you must also cut down the mightiest tree in the forest, '), nl,
  write('with a Herring! How do you respond?'), nl.

describe(knights_who_say_ni) :-
  assert(vocabulary(ni)),
  assert(vocabulary(we_need_a_shrubbery_for_the_nights_who_say_ni)),
  write('You are at the Knights who say Ni. To the south is the pathway '), nl,
  write('you were walking on to get here.'), nl, nl,
  write('You ask the Knights "May I get through?". The knights demand a'), nl,
  write('sacrifice! You tell the knights, "Please, I simply would like to pass through."'), nl,
  write('In response, the knights shout "Ni!", and exclaim that they will continue to'), nl,
  write('shout "Ni!" until you appease them with a shrubbery. You cannot stand the word'), nl,
  write('"Ni", so you must now find a shrubbery.'), nl.

describe(the_mightiest_tree_in_the_forest) :-
  write('You have arrived at the mightiest tree in the forest! Legend has it that this tree,'), nl,
  write('if cut down by a herring, can get you wherever you need to go'), nl.

describe(goal) :-
  write('Congratulations! You have gotten through the knights who say Ni! Use the command halt to'), nl,
  write('end the game.'), nl.

% These facts tell where various objects in the game are located.
at(old_crone, small_village).
at(herring, the_mightiest_tree_in_the_forest).

% This fact tells where I am currently located in the map.
i_am_at(fork_in_road).

% These facts tell which paths exist on the map.
path(large_village, e, fork_in_road).
path(fork_in_road, w, large_village).
path(fork_in_road, n, knights_who_say_ni).
path(knights_who_say_ni, s, fork_in_road).

path(the_mightiest_tree_in_the_forest, n, small_village).
path(small_village, s, the_mightiest_tree_in_the_forest).

path(knights_who_say_ni, n, goal) :- 
  holding(shrubbery), 
  !, nl.
path(knights_who_say_ni, n, goal) :-
  write('You do not have a shrubbery for the Knights who say Ni! You shall not pass!'), 
  nl, fail.

path(fork_in_road, e, small_village).
path(small_village, w, fork_in_road).

% These rules specify how to pick up an object.
take(X) :-
  holding(X),
  write('You''re already holding the'),
  write(X),
  write('.'),
  !, nl.

take(_) :-
  holding(Object),
  write('You can only hold one object at a time! Put down the '),
  write(Object),
  write(' you are holding.'),
  !, fail.

take(X) :- 
  i_am_at(Place),
  at(X, Place),
  retract(at(X, Place)),
  assert(holding(X)),
  write('Ok. You are now holding the '), write(X), write('.'),
  !, nl.

take(X) :-
  write('There is no '),
  write(X),
  write(' here.'),
  nl.


drop(X) :-
  holding(X),
  i_am_at(Place),
  retract(holding(X)),
  assert(at(X, Place)),
  write('OK.'),
  !, nl.

drop(_) :-
  write('You aren''t holding it!'),
  nl.


% These rules define moving around the world.
n :- go(n).
s :- go(s).
e :- go(e).
w :- go(w).

go(Direction) :-
  % Increment the counter.
  time_counter(N),
  M is N + 1,
  retract(time_counter(N)),
  assert(time_counter(M)),
  M < 7,
  i_am_at(Here),
  path(Here, Direction, There),
  retract(i_am_at(Here)),
  assert(i_am_at(There)),
  !, look.

go(_) :-
  time_counter(N),
  N < 7,
  write('You can''t go that way'),
  nl.

go(_) :-
  write('The knights have fallen asleep and you have failed on yoru quest!'), 
  nl.

look :-
  i_am_at(Place),
  describe(Place),
  nl,
  notice_objects_at(Place),
  nl.

notice_objects_at(Place) :-
  at(X, Place),
  write('There is a '),
  write(X),
  write(' here.'),
  nl,
  fail.

notice_objects_at(_).

tell(man_on_horse, we_need_a_shrubbery_for_the_nights_who_say_ni) :-
  assert(exists(shrubbery)),
  assert(at(shrubbery, small_village)),
  retract(talking_to(man_on_horse)),
  write('The man understands! He has decided to give you your shrubbery!'), nl,
  write('You should pick up the shrubbery! (use the take(shrubbery) command to pick it up)'), nl.

tell(knights_who_say_ni, it) :-
  retract(talking_to(knights_who_say_ni)),
  write('You have discovered that the knights can''t stand the word "it"! They cower away into'), nl,
  write('a corner. They don''t know what to do! They can no longer protect their pathway! The'), nl,
  write('Knights have now made a clearence for you, and you can pass. Your goal is to the north'), nl,
  write('of you now. You may go there.'), nl.
  
tell(_, _) :- 
  write('Looks like the person you''re talking to doesn''t understand what you are saying'),
  nl.

say(VocabularyWord) :-
  vocabulary(VocabularyWord),
  talking_to(Person),
  tell(Person, VocabularyWord),
  !, fail.

say(VocabularyWord) :-
  write('Looks like '), write(VocabularyWord), write(' isn''nt in your vocabulary'),
  nl.

vocab :- 
  vocabulary(Word),
  write(Word),
  nl,
  fail.

talk_to(old_crone) :-
  vocabulary(ni),
  assert(talking_to(man_on_horse)),
  write('You say "Ni". She flinches. You say "Ni" again, she flinches again. A man on a'), nl,
  write('horse rides by you and says that he laments the lack of law and order that'), nl,
  write('allows them to say "Ni" to an old woman. You now have to explain to this man'), nl,
  write('why you are doing this. What do you say to the man? (Look in your vocabulary to find a phrase)'), nl,
  !, fail.

talk_to(old_crone) :-
  write('You are not able to tell the old crone what you are looking for.'), nl,
  write('Maybe visit the Knights who say Ni first.'), nl.

finish :-
  nl,
  write('The game is over. Please enter the "halt." command.'),
  nl.

instructions :-
  nl,
  write('Enter commands using standard Prolog syntax.'), nl,
  write('Available commands are:'), nl,
  write('start.                -- to start the game.'), nl,
  write('n.  s.  e.  w.        -- to go in that direction.'), nl,
  write('take(Object).         -- to pick up an object.'), nl,
  write('drop(Object).         -- to put down an object.'), nl,
  write('talk_to(Person).      -- to talk to a person.'), nl,
  write('say(WocabularyWord).  -- to say a word in your vocabulary'), nl,
  write('vocab.                -- to look at your vocabulary.'), nl,
  write('look.                 -- to look around you again.'), nl,
  write('instructions.         -- to see this message again.'), nl,
  write('halt.                 -- to end the game and quit.'), nl,
  nl.

start :-
  instructions,
  look.









